package com.deco.logic.sys;

import com.deco.dao.delegate.sys.ICmsMenuDao;
import com.deco.dao.domain.table.CmsMenu;
import com.deco.domain.vo.sys.CmsMenuVo;
import com.deco.domain.vo.sys.CmsRoleVo;
import com.free.beanutils.BeanUtils;
import com.free.ext.logger.FreeLogger;
import com.free.ext.logger.FreeLoggerFactory;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

import javax.annotation.processing.RoundEnvironment;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 功能概述:
 * </p>
 * <p>
 * 功能详述:
 * </p>
 */
@Component
public class CmsMenuLogic {
    /*========================================================================*
     *                         Public Fields (公共属性)
     *========================================================================*/

    /*========================================================================*
     *                         Private Fields (私有属性)
     *========================================================================*/

    private static final FreeLogger LOGGER = FreeLoggerFactory.getLogger(CmsMenuLogic.class);

    @Autowired
    private ICmsMenuDao dao;

    @Autowired
    private CmsRoleLogic logic;
    /*========================================================================*
     *                         Construct Methods (构造方法)
     *========================================================================*/

    /*========================================================================*
     *                         Public Methods (公有方法)
     *========================================================================*/


    public List<CmsMenuVo> getAll(){
        CmsMenuVo menuVo = new CmsMenuVo();
        return dao.selectList(menuVo, StringUtils.EMPTY);
    }

    /**
     * 获得角色的所有菜单
     * @param roleId 角色ID
     * @return
     */
    public List<CmsMenuVo> getAllRoleTreeMenus(int roleId){
        List<CmsMenuVo> cmsAllMenus = getAllTreeMenus(0);
        List<String> menuIds = logic.getRoleMenus(String.valueOf(roleId));
        if(cmsAllMenus == null || cmsAllMenus.size() == 0){
            return new ArrayList<>();
        }
        if(menuIds == null || menuIds.size()== 0){
            return cmsAllMenus;
        }
        setRoleMenus(cmsAllMenus, menuIds);
        return cmsAllMenus;
    }

    /**
     * 根据用户角色显示用户菜单
     * @param roles 用户角色
     * @param curMenu 当前菜单
     * @return
     */
    public List<CmsMenuVo> getTreeMenusByRoles(String roles, String curMenu){
        LOGGER.info("角色{}获得菜单树",roles);
        List<String> roleMenuIds = logic.getRoleMenus(roles);
        if(roleMenuIds == null){
            LOGGER.info("角色{}没有对应的菜单",roles);
            return null;
        }
        List<CmsMenuVo> cmsAllMenus = getAllTreeMenus(0);
        if(cmsAllMenus == null || cmsAllMenus.size() ==0){
            return null;
        }
        List<CmsMenuVo> custMenus = new ArrayList<>();
        getCustAllMenus(cmsAllMenus,
                        custMenus,
                        roleMenuIds,
                        curMenu);
        return custMenus;
    }


    @Cacheable(value = "cacheMenus",key="#parentId")
    public List<CmsMenuVo> getAllTreeMenus(int parentId){
        return dao.selectMenusByParentId(parentId);
    }

    @CacheEvict(value="cacheMenus",allEntries=true)
    public int update(CmsMenuVo menu){
        return dao.update(menu);
    }

    @CacheEvict(value="cacheMenus",allEntries=true)
    public CmsMenuVo add(CmsMenuVo menu){
        return dao.add(menu);
    }

    @CacheEvict(value="cacheMenus",allEntries=true)
    public int delete(Integer key){
        int res = dao.delete(key);
        if(res > 0){
            CmsMenuVo vo = new CmsMenuVo();
            vo.setParentId(key);
            dao.deleteByCondition(vo);
        }
        return res;
    }

    @Cacheable(value = "cacheMenus",key="#id")
    public CmsMenuVo getById(int id){
        CmsMenuVo menu = new CmsMenuVo();
        menu.setId(id);
        return dao.selectOne(menu);
    }

    /*========================================================================*
     *                         Private Methods (私有方法)
     *========================================================================*/

    /**
     * 设置用户菜单信息
     * @param cmsAllMenus
     * @param roleMenus
     */
    private void setRoleMenus(List<CmsMenuVo> cmsAllMenus,
                              List<String> roleMenus){
        cmsAllMenus.forEach(x->{
            if(roleMenus.contains(x.getId().toString())){
                x.setActive(true);
            }
            if(x.getSubMenus() != null && x.getSubMenus().size() > 0){
                setRoleMenus(x.getSubMenus(), roleMenus);
            }
        });
    }

    /**
     * 获得用户菜单
     * @param cmsAllMenus 系统菜单
     * @param custMenus   返回结果
     * @param custMenuIds 用户角色菜单Id
     * @param curMenu     当前访问的url(用来设置状态)
     */
    private void getCustAllMenus(List<CmsMenuVo> cmsAllMenus,
                                 List<CmsMenuVo> custMenus,
                                 List<String> custMenuIds,
                                 String curMenu){
        String[] ingores = {"subMenus"};
        cmsAllMenus.forEach(x->{
            if(custMenuIds.contains(x.getId().toString())){
                CmsMenuVo tmp = new CmsMenuVo();
                BeanUtils.copyProperties(tmp,x,ingores);
                custMenus.add(tmp);
                tmp.setSubMenus(new ArrayList<>());
                if(StringUtils.isNotEmpty(x.getUrl())
                        && StringUtils.isNotEmpty(curMenu)
                        && x.getUrl().indexOf(curMenu) >=0){
                    tmp.setActive(true);
                }
                if(x.getSubMenus()!=null && x.getSubMenus().size()>0){
                    getCustAllMenus(x.getSubMenus(),tmp.getSubMenus(), custMenuIds, curMenu);
                    if(StringUtils.isNotEmpty(curMenu)){
                        boolean isExists = tmp.getSubMenus().stream().filter(y->{return y.getActive();}).findFirst().isPresent();
                        if(isExists){
                            tmp.setActive(true);
                        }
                    }
                }
            }
        });
    }


}
